#[derive(Copy, Clone)]
struct Date {
    y: u32,
    m: u8,
}
impl Date {
    fn new(y: u32, m: u8) -> Self {
        Self {y, m}
    }
}

impl Into<u32> for Date {
    fn into(self) -> u32 {
        self.y * 12 + (self.m as u32)
    }
}

impl From<u32> for Date {
    fn from(v: u32) -> Self {
        Date::new((v-1)/12, ((v-1)%12 + 1) as u8)
    }
}

fn retire_calc(
    reform_start_date: Date,
    origin_retire_age: u32,
    target_retire_age: u32,
    stride: u32,
    birth: Date) -> (Date, u32) {
    let reform_start_date = Into::<u32>::into(reform_start_date);
    let birth = Into::<u32>::into(birth);
    let reform_start_birth = reform_start_date - origin_retire_age * 12;
    let reform_progress_time = (target_retire_age - origin_retire_age) * 12 * stride;
    let reform_end_birth = reform_start_birth + reform_progress_time;
    if birth < reform_start_birth {
        (Date::from(birth + origin_retire_age * 12), 0)
    } else if birth >= reform_end_birth {
        (Date::from(birth + target_retire_age * 12), (target_retire_age - origin_retire_age) * 12)
    } else {
        let dm = birth - reform_start_birth;
        let additional = (dm / stride) + 1;
        (Date::from(birth + origin_retire_age * 12 + additional), additional)
    }
}


fn retire_time_inner(time: &str, tp: &str) -> Result<String, ()> {
    let sb: Vec<&str> = time.split('-').collect();
    if sb.len() != 2 {
        return Err(());
    }
    let a: u32 = sb[0].parse().map_err(|_|())?;
    let b: u8 = sb[1].parse().map_err(|_|())?;
    if b < 1 || b > 12 {
        return Err(());
    }
    let birth = Date::new(a, b).into();
    let (retire_date, additional_month) = match tp {
        "男职工" => retire_calc(Date::new(2025, 1), 60, 63, 4, birth),
        "原法定退休年龄55周岁女职工" => retire_calc(Date::new(2025, 1), 55, 58, 4, birth),
        "原法定退休年龄50周岁女职工" => retire_calc(Date::new(2025, 1), 50, 55, 2, birth),
        _ => return Err(()),
    };
    let age = Into::<u32>::into(retire_date) - Into::<u32>::into(birth);
    let age = age as f64 / 12f64;
    let age = format!("{:.2}", age);
    let age = age.trim_end_matches('0').trim_end_matches('.');
    Ok(format!("{}-{:02},{},{}",retire_date.y, retire_date.m, age, additional_month))
}

pub fn retire_time(time: &str, tp: &str) -> String {
    if let Ok(info) = retire_time_inner(time, tp) {
        info
    } else {
        "信息有误!".to_string()
    }
}
